﻿using System;
using System.Drawing;
using System.Reflection;
using System.Text.RegularExpressions;

namespace FrameWork.GDIPlus
{
    public static class ColorConverter
    {
        /// <summary>
        /// Gets the Color as a result of a background color overlapped by a color with a transparency.
        /// </summary>
        /// <param name="backColor">The background color.</param>
        /// <param name="blendColor">The overlapped color.</param>
        /// <param name="alpha">The alphablend value between 0 and 255.</param>
        /// <returns>A combinded color.</returns>
        public static Color AlphaBlendColor(Color backColor, Color blendColor, int alpha)
        {
            int r = Blend(blendColor.R, backColor.R, alpha);
            int g = Blend(blendColor.G, backColor.G, alpha);
            int b = Blend(blendColor.B, backColor.B, alpha);

            return Color.FromArgb(r, g, b);
        }


        private static int Blend(int value1, int value2, int alpha)
        {
            int d = value1 - value2;
            return (d * alpha) / 255 + value2;
        }

        /// <summary>
        /// Converts a 24 or less bit color to a 32 bit color with a alpha channel of 255 (opaque).
        /// </summary>
        /// <param name="color">The color without alpha channel.</param>
        /// <returns>The same color, but with alpha channel set to 255.</returns>
        public static Color OpaqueColor(Color color)
        {
            int argb = color.ToArgb() | (0xff << 24);
            return Color.FromArgb(argb);
        }

        /// <summary>
        /// Converts a 24 or less bit color to a 32 bit color with a specific alpha channel.
        /// </summary>
        /// <param name="c">The rgb color to convert.</param>
        /// <param name="alpha">The alpha value for the color.</param>
        /// <returns>The new color with alpha channel.</returns>
        public static Color AlphaColor(Color c, int alpha)
        {
            uint ualpha = (uint)alpha;
            ualpha = ualpha << 24;
            int mask = (int)ualpha;
            int v = c.B | (c.G << 8) | (c.R << 0x10) | mask;

            Color result = Color.FromArgb(v);
            return result;

        }
        public static Color FromString(string sColor)
        {
            sColor = sColor.Trim();
            if(sColor.StartsWith("#")){
                return FromHexString(sColor);
            }

            PropertyInfo[] pis = typeof(Color).GetProperties();
            foreach (PropertyInfo pi in pis)
            {
                if (pi.Name.ToLower() == sColor.ToLower())
                {
                    return (Color)pi.GetValue(null, null);
                }
            }
           
                 return Color.Empty;
           
            //sColor = sColor.ToLower();
        
            //switch (sColor)
            //{
            //    case "white":
            //        return Color.White;
            //    case "black":
            //        return Color.Black;
            //    case "gray":
            //        return Color.Gray;
            //    case "gold":
            //        return Color.Gold;
            //    case "green":
            //        return Color.Green;
            //    case "red":
            //        return Color.Red;
            //    case "blue":
            //        return Color.Blue;
            //    case "Silver":
            //        return Color.Silver

            //    default:
            //        return Color.Empty;
            //}
        }
        public static Color FromHexString(string hexColor)
        {
            string hc = ExtractHexDigits(hexColor);
            if (hc.Length != 6)
            {
                // you can choose whether to throw an exception
                //throw new ArgumentException("hexColor is not exactly 6 digits.");
                return Color.Empty;
            }
            string r = hc.Substring(0, 2);
            string g = hc.Substring(2, 2);
            string b = hc.Substring(4, 2);
            Color color = Color.Empty;
            try
            {
                int ri
                   = Int32.Parse(r, System.Globalization.NumberStyles.HexNumber);
                int gi
                   = Int32.Parse(g, System.Globalization.NumberStyles.HexNumber);
                int bi
                   = Int32.Parse(b, System.Globalization.NumberStyles.HexNumber);
                color = Color.FromArgb(ri, gi, bi);
            }
            catch
            {
                // you can choose whether to throw an exception
                //throw new ArgumentException("Conversion failed.");
                return Color.Empty;
            }
            return color;
        }
        /// <summary>
        /// Extract only the hex digits from a string.
        /// </summary>
        public static string ExtractHexDigits(string input)
        {
            // remove any characters that are not digits (like #)
            Regex isHexDigit
               = new Regex("[abcdefABCDEF\\d]+", RegexOptions.Compiled);
            string newnum = "";
            foreach (char c in input)
            {
                if (isHexDigit.IsMatch(c.ToString()))
                    newnum += c.ToString();
            }
            return newnum;
        }
    }
}
